package ru.agiledev.wikiservice;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import ru.agiledev.aos.morph.MorphAnalyzer;
import ru.agiledev.wiki.domain.transformed.Stem;
import ru.agiledev.wiki.domain.transformed.Word;
import ru.agiledev.wikiparser.util.HibernateUtil;

import javax.jws.WebService;
import java.util.*;

/**
 * Created by a.kirillov
 * Date: 11/14/11 Time: 5:51 PM
 */
@WebService(endpointInterface = "ru.agiledev.wikiservice.WiktionaryService")
public class WiktionaryServiceImpl implements WiktionaryService{
    /**
     * Method for creating stem form of word for query analyzer
     *
     * @param word input word in String format
     * @return LightWord with word value and set of stems
     */
    @Override
    public LWord getStemmedWord(String word){
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        Criteria criteria = session.createCriteria(Stem.class).add(Restrictions.eq("value", word));

        List<Stem> stems = criteria.list();

        LWord resultWord;
        if(stems.size()>0){
            Stem domainStem = (Stem) criteria.list().get(0);
            resultWord = toLightWord(domainStem);
            session.close();
        } else {
            session.close();
            MorphAnalyzer analyzer = new MorphAnalyzer();

            List<String> stemmedList = analyzer.stem(word);

            Stem stem = writeNewStemToDatabase(word, stemmedList);

            resultWord = toLightWord(stem);
        }
        return resultWord;
    }


    /*  *//**
     * Method creates new Stem and writes it into DB
     * @param word initial form of word
     * @param stemmedList list of word's stems
     * @return Stem
     */
    private Stem writeNewStemToDatabase(String word, List<String> stemmedList) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();

        Stem stem;

        if(stemmedList.size()>0){
            StringBuilder stringBuilder = new StringBuilder();
            for(String stemmedWord:stemmedList){
                stringBuilder.append(stemmedWord);
                stringBuilder.append("|");
            }
            stem = new Stem(word, stringBuilder.substring(0, stringBuilder.length()-1));
        } else stem = new Stem(word, "");//case when word have no stems. e.g. numerals such as 2010

        session.save(stem);
        session.getTransaction().commit();
        session.close();

        return stem;
    }

    /**
     * Transforming domain entity Stem to LWord
     * @param stem domain entity Stem
     * @return LightWord build on domain word
     */
    private LWord toLightWord(Stem stem){

        HashSet<String> stems = new HashSet<String>();
        if(stem.getStems().length()>0){
            Collections.addAll(stems, stem.getStems().split("\\|"));
        }

        LWord result = new LWord(stem.getValue(), stems);

        return result;
    }

    //synonyms, antonyms, hyponyms, hypernyms
    public ConceptObject getObjectConceptualEnvironment(String word){
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        Criteria criteria = session.createCriteria(Word.class).add(Restrictions.eq("word", word));

        List<Word> words = criteria.list();

        if(words.size()>0){
            Word w = words.get(0);

            List<String> synonyms;
            List<String> antonyms;
            List<String> hypernyms;
            List<String> hyponyms;

            String syns = w.getSynonyms();
            if(syns.length()>0){
                synonyms = Arrays.asList(syns.replace("частичн.: ","").split(", "));
            } else {
                synonyms = new ArrayList<String>(1);
            }

             String hyps = w.getHyponyms();
            if(syns.length()>0){
                hyponyms = Arrays.asList(hyps.replace("частичн.: ","").split(", "));
            } else {
                hyponyms = new ArrayList<String>(1);
            }
             String ants = w.getAntonyms();
            if(syns.length()>0){
                antonyms = Arrays.asList(ants.replace("частичн.: ","").split(", "));
            } else {
                antonyms = new ArrayList<String>(1);
            }

             String hypers = w.getHypernyms();
            if(syns.length()>0){
                hypernyms = Arrays.asList(hypers.replace("частичн.: ","").split(", "));
            } else {
                hypernyms = new ArrayList<String>(1);
            }

            session.close();
            return new ConceptObject(word, synonyms, antonyms, hyponyms, hypernyms);
        }
        session.close();
        return null;
    }
}
